package com.northpool.operator.analysis.overlap;

import com.northpool.operator.annotation.InputParam;
import com.northpool.operator.annotation.InputParams;
import com.northpool.operator.annotation.OperatorInfo;
import com.northpool.operator.annotation.OutputParam;
import com.northpool.operator.annotation.OutputParams;
import com.northpool.operator.common.algorithm.OperatorTestBuild;
import com.northpool.operator.common.algorithm.TestParamBuilder;
import com.northpool.operator.common.database.DatabaseUtils;
import com.northpool.operator.common.stpclient.StpClientOperatorBase;
import com.northpool.operator.param.ParamTool;
import com.northpool.operator.param.custom.DatasetParam;
import com.northpool.operator.type.TypeEnum;
import com.northpool.stpclient.bean.BaseResponse;
import com.northpool.stpclient.modules.geoprocess.operator.IPipelineOperator;
import com.northpool.stpclient.operator.bean.DatasetBean;
import com.northpool.stpclient.operator.bean.OperatorBean;
import com.northpool.stpclient.operator.bean.ParamBean;
import com.northpool.stpclient.operator.bean.PipelineBean;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

@OperatorInfo(
        ref = "IntersectDiffOperator",
        name = "交集取反",
        description = "叠加分析-交集取反"
)
@OutputParams({
        @OutputParam(ref = "dataset", name = "结果数据集"),
        @OutputParam(ref = "dataSourceId", name = "结果数据源ID"),
        @OutputParam(ref = "tableName", name = "结果表名称"),
})
public class IntersectDiffOperator extends StpClientOperatorBase {
    String dataSourceIdA;
    String tableNameA;
    String spatialFieldA;
    String sqlFilterA;
    String dataSourceIdB;
    String tableNameB;
    String spatialFieldB;
    String sqlFilterB;
    String targetDataSourceId;
    String targetTableName;

    @InputParams({
            @InputParam(ref = "datasetA", name = "数据集A", desc = "数据集包含数据源ID和数据表名称的JSON描述，如: {\"dataSourceId\":\"xxx-xxx\",\"tableName\":\"table\"}", type = TypeEnum.DB, required = true),
            @InputParam(ref = "spatialFieldA", name = "空间字段A", desc = "空间字段名称，如: geom", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "sqlFilterA", name = "SQL过滤条件A", desc = "SQL过滤条件, 如: dlmc = '旱地'", type = TypeEnum.STRING, required = false),
            @InputParam(ref = "datasetB", name = "数据集B", desc = "数据集包含数据源ID和数据表名称的JSON描述，如: {\"dataSourceId\":\"xxx-xxx\",\"tableName\":\"table\"}", type = TypeEnum.DB, required = true),
            @InputParam(ref = "spatialFieldB", name = "空间字段B", desc = "空间字段名称，如: geom", type = TypeEnum.STRING, required = true),
            @InputParam(ref = "sqlFilterB", name = "SQL过滤条件B", desc = "SQL过滤条件, 如: dlmc = '旱地'", type = TypeEnum.STRING, required = false),
            @InputParam(ref = "targetDataSourceId", name = "目标数据源ID", type = TypeEnum.DATASOURCE, required = true),
            @InputParam(ref = "targetTableName", name = "目标表名称", desc = "目标表名称", type = TypeEnum.STRING, required = true),
    })
    public IntersectDiffOperator() {
        super();
    }

    public static void main(String[] args) throws Exception {
        OperatorTestBuild.execute(IntersectDiffOperator.class, TestParamBuilder.aBuilder()
                .param("datasetA", "{\"dataSourceId\":\"highgo\",\"tableName\":\"public.cun_4301\"}")
                .param("spatialFieldA", "shape")
                .param("datasetB", "{\"dataSourceId\":\"highgo\",\"tableName\":\"public.cun_4301\"}")
                .param("spatialFieldB", "shape")
                .param("targetDataSourceId", "kjklz")
                .param("targetDataSourceId", "result.叠加交集取反结果")
                .build());
    }

    @Override
    public void execute(ParamTool params) throws Exception {
        DatasetParam datasetA = params.getDataset("datasetA");
        DatasetParam datasetB = params.getDataset("datasetB");

        this.dataSourceIdA = datasetA.getDataSourceId();
        this.tableNameA = datasetA.getTableName();
        this.spatialFieldA = params.getStr("spatialFieldA");
        this.sqlFilterA = params.getStr("sqlFilterA");
        this.dataSourceIdB = datasetB.getDataSourceId();
        this.tableNameB = datasetB.getTableName();
        this.spatialFieldB = params.getStr("spatialFieldB");
        this.sqlFilterB = params.getStr("sqlFilterB");
        this.targetDataSourceId = params.getStr("targetDataSourceId");
        this.targetTableName = params.getStr("targetTableName");

        String targetDataset = DatabaseUtils.buildDatasetJson(this.targetDataSourceId, this.targetTableName);
        this.result("dataset", targetDataset);
        this.result("dataSourceId", this.targetDataSourceId);
        this.result("tableName", this.targetTableName);

        PipelineBean pipeline = new PipelineBean();
        pipeline.setResultFile(System.getProperty("user.dir") + File.separator + "result_file");
        DatasetBean dataSet = new DatasetBean();
        dataSet.setDataSourceId(dataSourceIdA);
        dataSet.setTableName(tableNameA);
        dataSet.setSqlFilter(sqlFilterA);
        pipeline.setDataSet(dataSet);

        List<OperatorBean> ops = new LinkedList<>();
        ops.add(buildErase());
        ops.add(buildPgSink());

        pipeline.setOperators(ops);
        IPipelineOperator iPipelineOperator = this.client.pipelineOperator();
        BaseResponse response = iPipelineOperator.startPipeline(pipeline);
        iPipelineOperator.onStart(response.getRequestId(), () -> {
            this.log("叠加分析开始");
        });
        iPipelineOperator.onSuccess(response.getRequestId(), () -> {
            this.log("叠加分析成功");
            String log = iPipelineOperator.log(response.getRequestId());
            this.log(log);
            this.successExit();
        });
        iPipelineOperator.onError(response.getRequestId(), () -> {
            this.error("叠加分析失败");
            String log = iPipelineOperator.log(response.getRequestId());
            this.error(log);
            this.failedExit();
        });
        this.waiting(24);
    }

    public OperatorBean buildErase() {
        OperatorBean operatorBean = new OperatorBean();
        operatorBean.setClassName("com.northpool.stpprocess.operator.spatial.analysis.IntersectDiffOperator");

        List<ParamBean> params = new LinkedList<>();
        params.add(new ParamBean("originSpatialField", spatialFieldA));
        params.add(new ParamBean("dataSourceId", dataSourceIdB));
        params.add(new ParamBean("tableName", tableNameB));
        params.add(new ParamBean("spatialField", spatialFieldB));
        params.add(new ParamBean("sqlFilter", sqlFilterB));
        operatorBean.setStartParam(params);

        return operatorBean;
    }

    public OperatorBean buildPgSink() {
        OperatorBean operatorBean = new OperatorBean();
        operatorBean.setClassName("com.northpool.stpprocess.operator.basic.sink.PostgresSink");

        List<ParamBean> params = new LinkedList<>();
        params.add(new ParamBean("dataSourceId", targetDataSourceId));
        params.add(new ParamBean("tableName", targetTableName));
        params.add(new ParamBean("templateDataSourceId", dataSourceIdA));
        params.add(new ParamBean("templateTableName", tableNameA));
        operatorBean.setStartParam(params);

        return operatorBean;
    }
}
